home *** CD-ROM | disk | FTP | other *** search
/ PC Media 7 / PC MEDIA CD07.iso / share / prog / cm / cmlist.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-06  |  7.9 KB  |  360 lines

  1. // CmList.cpp
  2. // -----------------------------------------------------------------
  3. // Compendium - C++ Container Class Library
  4. // Copyright (C) 1992-1994, Glenn M. Poorman, All rights reserved
  5. // -----------------------------------------------------------------
  6. // Singly linked list implementation.
  7. // -----------------------------------------------------------------
  8.  
  9. #include <cm/include/cmlist.h>
  10.  
  11.  
  12. // "CmLinkedList" is the list copy constructor.
  13. //
  14. CmLinkedList::CmLinkedList(const CmLinkedList& Li)
  15. {
  16.   _first = _last = NULL;
  17.   copy(Li);
  18. }
  19.  
  20.  
  21. // "~CmLinkedList" is the list destructor.
  22. //
  23. CmLinkedList::~CmLinkedList()
  24. {
  25.   removeAll();
  26. }
  27.  
  28.  
  29. // "=" assignment operator copies the contents of the specified list
  30. // into this list.
  31. //
  32. CmLinkedList& CmLinkedList::operator=(const CmLinkedList& Li)
  33. {
  34.   if (&Li != this)
  35.   {
  36.     removeAll();
  37.     copy     (Li);
  38.   }
  39.   return *this;
  40. }
  41.  
  42.  
  43. // "[]" indexing operator allows an object to be retrieved from the
  44. // list by index like an array.
  45. //
  46. CmObject* CmLinkedList::operator[](int idx) const
  47. {
  48.   if (idx < 0 || idx >= _size) return NULL;
  49.  
  50.   int     ii    = 0;
  51.   CmLink *rover = _first;
  52.   while (rover && ii < idx)
  53.   {
  54.     rover = rover->_next;
  55.     ii++;
  56.   }
  57.   return (rover) ? rover->_data : NULL;
  58. }
  59.  
  60.  
  61. // "add" adds the specified object to the end of this list.
  62. //
  63. Bool CmLinkedList::add(CmObject* pObj)
  64. {
  65.   return append(pObj);
  66. }
  67.  
  68.  
  69. // "append" adds the specified object to the end of this list.
  70. //
  71. Bool CmLinkedList::append(CmObject* pObj)
  72. {
  73.   if (!pObj) return FALSE;
  74.   CmLink *newlink = new CmLink(pObj);
  75.   if (!newlink) return FALSE;
  76.  
  77.   if (!_first)
  78.     _first = _last = newlink;
  79.   else
  80.   {
  81.     _last->_next = newlink;
  82.     _last        = newlink;
  83.   }
  84.   _size++;
  85.   return TRUE;
  86. }
  87.  
  88.  
  89. // "prepend" adds the specified object to the start of this list.
  90. //
  91. Bool CmLinkedList::prepend(CmObject* pObj)
  92. {
  93.   if (!pObj) return FALSE;
  94.   CmLink *newlink = new CmLink(pObj);
  95.   if (!newlink) return FALSE;
  96.  
  97.   if (!_first)
  98.     _first = _last = newlink;
  99.   else
  100.   {
  101.     newlink->_next = _first;
  102.     _first         = newlink;
  103.   }
  104.   _size++;
  105.   return TRUE;
  106. }
  107.  
  108.  
  109. // "insertAfter" searches for the first occurrence of an object that
  110. // isEqual to the first specified object and inserts the second
  111. // specified object immediately after.
  112. //
  113. Bool CmLinkedList::insertAfter(CmObject* after, CmObject* pObj)
  114. {
  115.   if (!after || !pObj || !_first) return FALSE;
  116.  
  117.   CmLink *rover = _first;
  118.   Bool    found = FALSE;
  119.   while (rover && !found)
  120.   {
  121.     if (rover->_data->isEqual(after)) found = TRUE;
  122.     else                              rover = rover->_next;
  123.   }
  124.  
  125.   if (!found) return FALSE;
  126.  
  127.   CmLink *newlink = new CmLink(pObj);
  128.   if (!newlink) return FALSE;
  129.   newlink->_next = rover->_next;
  130.   rover->_next = newlink;
  131.   if (rover == _last) _last = newlink;
  132.   _size++;
  133.   return TRUE;
  134. }
  135.  
  136.  
  137. // "insertBefore" searches for the first occurrence of an object that
  138. // isEqual to the first specified object and inserts the second
  139. // specified object immediately before.
  140. //
  141. Bool CmLinkedList::insertBefore(CmObject* before, CmObject* pObj)
  142. {
  143.   if (!before || !pObj || !_first) return FALSE;
  144.  
  145.   CmLink *rover1 = _first;
  146.   CmLink *rover2 = _first;
  147.  
  148.   while (rover1 != NULL && !(rover1->_data->isEqual(before))) 
  149.   {
  150.     rover2 = rover1;
  151.     rover1 = rover1->_next;
  152.   }
  153.  
  154.   if (rover1 == NULL) return FALSE;
  155.  
  156.   CmLink *newlink = new CmLink(pObj);
  157.   if (rover1 == rover2)
  158.   {
  159.     newlink->_next = _first;
  160.     _first         = newlink;
  161.   }
  162.   else
  163.   {
  164.     newlink->_next = rover2->_next;
  165.     rover2->_next  = newlink;
  166.   }
  167.   _size++;
  168.   return TRUE;
  169. }
  170.  
  171.  
  172. // "remove" removes the first occurrence of an object that isEqual
  173. // to the specified object from the list.
  174. //
  175. Bool CmLinkedList::remove(CmObject* pObj)
  176. {
  177.   if (!pObj || !_first) return FALSE;   // Return if no objects.
  178.  
  179.   if (_first->_data->isEqual(pObj))     // Object to remove is first.
  180.   {
  181.     CmObject* pObj = removeFirst();
  182.     if (!pObj) return FALSE;
  183.     if (ownsObjects()) delete pObj;
  184.     return TRUE;
  185.   }
  186.  
  187.   CmLink *rover1 = _first;              // Search for object to remove.
  188.   CmLink *rover2 = _first;
  189.  
  190.   while (rover1 != NULL && !(rover1->_data->isEqual(pObj)))
  191.   {
  192.     rover2 = rover1;
  193.     rover1 = rover1->_next;
  194.   }
  195.  
  196.   if (rover1 == NULL) return FALSE;     // Object was not found.
  197.  
  198.   if (rover1 == _last)                  // Object was last in list.
  199.   {
  200.     CmObject* pObj = removeLast();
  201.     if (!pObj) return FALSE;
  202.     if (ownsObjects()) delete pObj;
  203.     return TRUE;
  204.   }
  205.  
  206.   rover2->_next = rover2->_next->_next;     // Remove object from list.
  207.  
  208.   if (ownsObjects()) delete rover1->_data;  // Delete if object if owned.
  209.   delete rover1;                            // Delete link.
  210.   _size--;
  211.   return TRUE;
  212. }
  213.  
  214.  
  215. // "removeFirst" removes the first object from the list.  The object is
  216. // not deleted regardless of the ownership.
  217. //
  218. CmObject* CmLinkedList::removeFirst()
  219. {
  220.   if (!_first) return NULL;
  221.  
  222.   CmObject *pObj = _first->_data;
  223.   CmLink   *temp = _first;
  224.   _first = _first->_next;
  225.   if (!_first) _last = NULL;
  226.   delete temp;
  227.   _size--;
  228.   return pObj;
  229. }
  230.  
  231.  
  232. // "removeLast" removes the last object from the list.  The object is
  233. // not deleted regardless of the ownership.
  234. //
  235. CmObject* CmLinkedList::removeLast()
  236. {
  237.   if (!_last) return NULL;
  238.   if (_last == _first) return removeFirst();
  239.  
  240.   CmLink *rover = _first;
  241.   while (rover->_next->_next)
  242.     rover = rover->_next;
  243.   CmObject *pObj = rover->_next->_data;
  244.   delete rover->_next;
  245.   _last = rover;
  246.   _last->_next = NULL;
  247.   _size--;
  248.   return pObj;
  249. }
  250.  
  251.  
  252. // "lookup" returns the first occurrence of an object which isEqual
  253. // to the specified object.
  254. //
  255. CmObject* CmLinkedList::lookup(CmObject* pObj) const
  256. {
  257.   if (!pObj || !_first) return FALSE;
  258.  
  259.   CmLink *rover = _first;
  260.   Bool    found = FALSE;
  261.   while (rover && !found)
  262.   {
  263.     if (rover->_data->isEqual(pObj)) found = TRUE;
  264.     else                             rover = rover->_next;
  265.   }
  266.   return (found) ? rover->_data : NULL;
  267. }
  268.  
  269.  
  270. // "contains" checks to see if an object that isEqual to the specified
  271. // object exists in the list.
  272. //
  273. Bool CmLinkedList::contains(CmObject* pObj) const
  274. {
  275.   if (!pObj || !_first) return FALSE;
  276.  
  277.   CmLink *rover = _first;
  278.   Bool    found = FALSE;
  279.   while (rover && !found)
  280.   {
  281.     if (rover->_data->isEqual(pObj)) found = TRUE;
  282.     else                             rover = rover->_next;
  283.   }
  284.   return found;
  285. }
  286.  
  287.  
  288. // "occurrences" returns the number of objects in the list
  289. // isEqual to the specified object.
  290. //
  291. unsigned CmLinkedList::occurrences(CmObject* pObj) const
  292. {
  293.   if (!pObj || !_first) return 0;
  294.  
  295.   CmLink   *rover = _first;
  296.   unsigned  total = 0;
  297.   while (rover)
  298.   {
  299.     if (rover->_data->isEqual(pObj)) total++;
  300.     rover = rover->_next;
  301.   }
  302.   return total;
  303. }
  304.  
  305.  
  306. // "removeAll" removes all the objects from the list.
  307. //
  308. void CmLinkedList::removeAll()
  309. {
  310.   CmLink *temp, *rover = _first;
  311.   while (rover)
  312.   {
  313.     temp = rover->_next;
  314.     if (ownsObjects()) delete rover->_data;
  315.     delete rover;
  316.     rover = temp;
  317.   }
  318.   _size  = 0;
  319.   _first = _last = NULL;
  320. }
  321.  
  322.  
  323. // "newIterator" creates and returns a list iterator.
  324. //
  325. CmIterator* CmLinkedList::newIterator() const
  326. {
  327.   return new CmLinkedListIterator(*this);
  328. }
  329.  
  330.  
  331. // "next" returns the current object in the list and increments the
  332. // iterator to the next link.
  333. //
  334. CmObject* CmLinkedListIterator::next()
  335. {
  336.   if (!_link) return NULL;
  337.   CmObject *rval = _link->_data;
  338.   _link = _link->_next;
  339.   return rval;
  340. }
  341.  
  342.  
  343. // "previous" backs the iterator up one object and returns that object.
  344. //
  345. CmObject* CmLinkedListIterator::previous()
  346. {
  347.   if (!_link) return NULL;
  348.   CmObject *rval = _link->_data;
  349.   if (_link == _list._first)
  350.     _link = NULL;
  351.   else
  352.   {
  353.     CmLink *rover = _list._first;
  354.     while (rover && rover->_next != _link)
  355.       rover = rover->_next;
  356.     _link = rover;
  357.   }
  358.   return rval;
  359. }
  360.